-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trim pulse's Shape
to envelopes
#818
Conversation
@stavros11 and @hay-k I asked you a review immediately, such that you could comment on the overall strategy before I keep going to apply it to the whole file. The new part is down to |
94a5c0a
to
f50f7ae
Compare
@stavros11 and @hay-k, feature-wise the PR should be complete, now I need to fix the tests and propagate the changes. If you'd start having a look you could already provide some feedback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @alecandido. One question and another point from my side.
Question: is there any case where times
is not something like np.linspace(0, duration, nsamples)
(where nsamples = sampling_rate * duration)
)? Is this array supposed to be generated in all drivers calling the pulse.i
and pulse.q
methods?
The other point is about the way we are handling i and q, which seems to me as kind of reinventing complex numbers. Since we are using numpy, which supports complex numbers, maybe we could simplify by returing the envelopes/shapes as complex numbers and let the user do .real
/.imag
to grab the i
/q
component respectively. For example the modulate
operation would look much simpler:
return np.exp(1j * phases) * envelope / np.sqrt(2)
and we would not have to define three functions (i
, q
, envelopes
) everywhere.
In 0.1 we are already using complex in the results
Line 18 in 5953517
self.voltage: npt.NDArray[np.complex128] = data |
which is already asymmetric to the pulse API (however that's fair since we have not discussed results on 0.2 yet).
Thanks for asking: the honest answer is "I don't know". However, here I started with the assumption that I wanted to evaluate a function on some points. Then, I had to change my mind. |
Concerning this, I have little experience with the drivers, so I don't know whether they are going to consume this information separately, or as complex numbers. In any case, I believe it is valuable to keep |
Probably most instruments instruments do not support uploading complex waveforms (but maybe ZI does?), but even in that case I would be fine doing waveform = pulse.envelope(...)
upload_to_instrument...({"i": waveform.real, "q": waveform.imag}) over upload_to_instrument...({"i": pulse.i(...), "q": pulse.q(...)}) if the former helps simplifying other parts of qibolab. |
waveform = pulse.envelopes(...)
upload_to_instrument...({"i": waveform[0], "q": waveform[1]}) This is already possible. We could follow PEP 20 and drop an alternative. However, I'm not sure whether a |
Yes, I am aware of |
@stavros11 usually complex numbers are useful in electronics, because it's simpler to integrate/derive exponentials, and it's easier to compose them (multiplication would just sum the exponents). |
512717b
to
1428c55
Compare
@hay-k @stavros11: to me, the current layout of If you have any further comment about the strategy, now it's the best timing :) I applied @stavros11 proposal concerning |
I believe I achieved a new record:
(i.e. everyone depended on |
I'm going to fix the tests in a quick and dirty way (the least dirty the best, of course). The message is: I'll delegate tests improvements to everyone that is going to improve the corresponding source, as more competent on the matter (I believe is a sensible attitude for every PR, since the goal is minimizing the changes). If anyone at any time (mainly @stavros11 and @hay-k) has a chance to decouple some tests from the Instead, I'm going to take care of shapes-specific tests. |
I'm actually keeping the same signature as before for pulses envelopes, since However:
|
0725bc1
to
7993aec
Compare
a25c4de
to
1f58990
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## 0.2 #818 +/- ##
==========================================
- Coverage 49.52% 48.75% -0.77%
==========================================
Files 59 61 +2
Lines 5642 5532 -110
==========================================
- Hits 2794 2697 -97
+ Misses 2848 2835 -13
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
57b9da7
to
55754a0
Compare
Co-authored-by: Hayk Sargsyan <[email protected]>
8d74b7f
to
6f4c84b
Compare
Just rebased. I will merge as soon as the tests pass. |
The current
PulseShape
has quite a verbose implementation, but essentially it holds functions for the shape envelopes. I will try to retain only that, delegating everything else outside (including the determination of the number of samples).PulseShape.eval
)pydantic
amplitude
out of envelopesduration
out of envelopes (back toPulse
)Shape
to envelopes #818 (comment)dropPulseType
There is also a further issue that has been discussed, but without a clear conclusion (#818 (comment)).
relative_phase
My personal take is that this is a modulation problem, since, for as long as the I and Q components are kept separate, and the information about
relative_phase
is retained, there is nothing lost and nothing to be done. Only when you want to mix them, you should consume therelative_phase
info.In any case, it is definitely not intrinsically related to shapes/envelopes, that are the core of this PR, so I'd rather open a separate issue.